package Day6;

import org.junit.Test;

import java.util.*;

/**
 * @author ：Yan Guang
 * @date ：Created in 2020/5/2 13:42
 * @description：泛型不能是基本数据类型 2.在集合中使用泛型:
 * 总结:
 * ①集合接口或集合类在jdk5. e时都修改为带泛型的结构。
 * ②在实例化集合类时，可以指明具体的泛型类型
 * ③指明完以后，在集合类或接口中凡是定义类或接口时，内部结构(比如:方法、
 * 比如: add(E e) --->实例化以后: add(Integer e)
 * ④注意点:泛型的类型必须是类，不能是基本数据类型。需要用到基本数据类型白
 * ⑤如果实例化时，没有指明泛型的类型。默认类型为java. Lang. object类型。
 * <p>
 * (由于子类在继承带泛型的父类时，指明了泛型类型。则实例化子类对象时，子类实例化耳朵时候不需要再指明
 */
public class GenericTest {
    @Test
    public void test1() {
        ArrayList list = new ArrayList();

        list.add(78);
        list.add(28);
        list.add(98);
        list.add(48);
        //问题一
//        list.add("Tom");

        for (Object o : list) {
            //出现了一个其它类型的变量Tom,需要引入泛型
            int stuScore = (Integer) o;

            System.out.println(stuScore);
        }
    }

    @Test
    public void test2() {
        ArrayList<Integer> integers = new ArrayList<>();
        integers.add(4324);//限制了数据类型
        integers.add(78);
        integers.add(28);
        integers.add(98);
        integers.add(48);
        //问题一
//        list.add("Tom");

        for (Integer integer : integers) {
            //不用强转
            System.out.println(integer);
        }
        //用迭代器遍历
        Iterator<Integer> iterator = integers.iterator();
        while (iterator.hasNext()) {
            int s = iterator.next();
            System.out.println(s);
        }
    }

    @Test
    public void test3() {

        Map<String, Integer> map = new HashMap<String, Integer>();
        map.put("Tom", 87);
        map.put("Jerry", 87);
        map.put("Jack", 67);
//        map.put(123, "ABC");
        //泛型的嵌套
        Set<Map.Entry<String, Integer>> entry = map.entrySet();
        Iterator<Map.Entry<String, Integer>> iterator = entry.iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, Integer> e = iterator.next();
            String key = e.getKey();
            Integer value = e.getValue();
            System.out.println(key + "---->" + value);
        }
    }

    //泛型方法：在方法中出现了泛型结构,可以先不确定数据类型,用的时候再灵活改变
    // 泛型方法在调用时，指明泛型参数的类型。
    //泛型方法可以声明为静态的，因为参数是调用的时候确定的
//    @Test
//    public <E> List<E> test4(E[] arr) {
//        ArrayList<E> list = new ArrayList<>();
//        for (E e : arr) {
//            list.add(e);
//        }
//        return list;
//    }

    @Test
    public void test5() {
        List<Object> list1 = null;
        List<String> list2 = null;
//    此时的ist1和ist2的类型不具有于父类关系,并列关系不可，只有继承关系才可以赋，也叫多态
//        list1!=list2;|

    }

    /**
     * 通配符的使用
     * 通配符？
     * 类A是类B的父类，G<A>和G<B> 是没有关系的，二者共同的父类是: G<?>
     *有限制条件的通配符的使用。
     * ? extends A:
     * G<? extends A>可以作为G<A>和G<B>的父类， 其中B是A的子类,也就是小于等于person，所以最小只能写到person，只能用比person大的，比附object
     * ? super A:
     * G<? super A>可以作为G<A>和G<B>的父类， 其中B是A的父类，也就是说大于等于person，所以只能写Object
     *
     */
    @Test
    public void test6() {
        List<Object> list1 = null;
        List<String> list2 = null;
        List<?> list = null;
        list = list1;
        list = list2;
//        打印成功的！
//        print(list1);
//        print(list2);

        List<String> list3 = new ArrayList<>();
        list3.add("AA");
        list3.add("BB");
        list3.add("CC");

        list = list3;
        //添加

//            list.add("DD");//使用通配符就不能向其中添加数据了
        //除了添加null
        list.add(null);

        Object o = list.get(0);
        System.out.println(o);
    }

    public void print(List<?> list) {
        Iterator<?> iterator = list.iterator();
        while (iterator.hasNext()) {
            Object obj = iterator.next();
            System.out.println(obj);
        }
    }


}
